package com.yueke.gemini.utils;


import com.bizvane.sun.common.utils.LogUtil;
import org.apache.logging.log4j.Logger;

import javax.activation.MimetypesFileTypeMap;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

/**
 * 说明：请求第三方接口
 * Created by admin on 2016/7/6.
 */
public class RestUtils {
    private static Logger log = LogUtil.getLogger(RestUtils.class);
    private static final int TIME_OUT = 6 * 1000;

    public static String sendRequest(String apiURL, Map<String, String> params, String method) throws Exception {
        String queryString = (null == params) ? "" : delimit(params.entrySet(), true);
        return sendRequest_buff(apiURL, queryString, method);
    }

    public static String sendRequest_buff(String apiURL, String params, String method) throws Exception {
        return sendRequest_buff(apiURL, params, method, false);
    }


    public static String sendRequest_buff(String apiURL, String params, String method, boolean keepAlive) throws Exception {
        log.info("url:" + apiURL);
        if (StringUtil.isNotNull(params)) {
            log.info("params :" + (params.length() > 3000 ? params.substring(0, 3000) : params));
        }
        method = StringUtil.valueOf(method, "POST");
        log.info("sendRequest_buff params:"+params);
        HttpURLConnection conn = (HttpURLConnection) new URL(apiURL).openConnection();
        conn.setRequestMethod(method.toUpperCase());

        if (keepAlive) {
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setConnectTimeout(60 * 1000);
        } else
            conn.setConnectTimeout(TIME_OUT);

        conn.setDoInput(true);
        //conn.setInstanceFollowRedirects(false);
        if ("post".equalsIgnoreCase(method)) {
            conn.setUseCaches(false);    //POST不能用缓存
        }
        if (StringUtil.isNotNull(params)) {
            conn.setDoOutput(true);
            conn.getOutputStream().write(params.getBytes("utf-8"));
        }
        conn.connect();

        log.info(toCustomString(conn.getHeaderFields()));

        if (conn.getResponseCode() != 200) {
            log.error("server status:" + conn.getResponseCode());
            throw new Exception("请求url失败");
        }

        //获取返回值
        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        bis = new BufferedInputStream(conn.getInputStream());
        for (int len = 0; (len = bis.read(buf)) != -1; ) {
            baos.write(buf, 0, len);
        }
        log.info("chareset:"+conn.getContentType());
        String charset = getChareset(conn.getContentType());
        String resultString = baos.toString(charset);
        log.info("resultString:"+baos.toString());


//        String charset = getChareset(conn.getContentType());
//        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
//        StringBuffer buffer = new StringBuffer();
//        String line;
//        while ((line = reader.readLine()) != null) {
//            buffer.append(line);
//        }
//        reader.close();
//
//
//        conn.disconnect();
//        log.info("RestUtils result:"+buffer.toString());
//        return buffer.toString();

        log.info("RestUtils result:" + resultString);
        return resultString;
    }

    public static String getChareset(String contentType) {
        int i = contentType == null ? -1 : contentType.indexOf("charset=");
        return i == -1 ? "UTF-8" : contentType.substring(i + 8);
    }

    public static String delimit(Collection<Map.Entry<String, String>> entries,
                                 boolean doEncode) throws UnsupportedEncodingException {
        if (entries == null || entries.isEmpty()) {
            return null;
        }
        StringBuffer buffer = new StringBuffer();
        boolean notFirst = false;
        for (Map.Entry<String, ?> entry : entries) {
            if (notFirst) {
                buffer.append("&");
            } else {
                notFirst = true;
            }
            Object value = entry.getValue();
            if (value == null) value = "";
            buffer.append(doEncode ? URLEncoder.encode(entry.getKey(), "UTF8") : entry.getKey()).append("=").append(
                    doEncode ? URLEncoder.encode(value.toString(), "UTF8") : value);
        }
        return buffer.toString();
    }


    public static String sendRequest(String apiURL, Map<String, String> params, String method, File file) throws Exception {
        if (file == null || !file.exists()) {
            throw new Exception("file is not exists!");
        }
        String queryString = (null == params) ? "" : delimit(params.entrySet(), true);
        return sendRequest_buff(apiURL, queryString, method, new FileInputStream(file), file.length(), file.getName(), new MimetypesFileTypeMap().getContentType(file));
    }

    public static String sendRequest_buff(String apiURL, String params, String method, InputStream in, long file_length, String file_name, String contentType) throws Exception {


        String boundary = "----------" + System.currentTimeMillis();

        HttpURLConnection conn = (HttpURLConnection) new URL(apiURL).openConnection();
        conn.setRequestMethod(method);
        conn.setConnectTimeout(TIME_OUT);

        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);


        if (ValidatorUtil.isNotNull(params)) {
            conn.getOutputStream().write(params.getBytes("utf-8"));
        }

        conn.connect();

        StringBuffer strBuf = new StringBuffer();
        strBuf.append("--").append(boundary).append("\r\n");
        strBuf.append("Content-Disposition: form-data; name=\"media\"; filelength=\"" + file_length + "\"; filename=\"" + file_name + "\"\r\n");
        strBuf.append("Content-Type:" + contentType + "\r\n\r\n");

        OutputStream out = new DataOutputStream(conn.getOutputStream());
        out.write(strBuf.toString().getBytes("utf-8"));


        int bytes;
        byte[] bufferOut = new byte[1024];
        while ((bytes = in.read(bufferOut)) != -1) {
            out.write(bufferOut, 0, bytes);
        }

        in.close();
        out.write(("\r\n--" + boundary + "--\r\n").getBytes("utf-8"));
        out.flush();
        out.close();
        conn.disconnect();

        if (conn.getResponseCode() != 200) {
            log.error("server status->" + conn.getResponseCode());
            throw new Exception("请求url失败");
        }


        String charset = getChareset(conn.getContentType());
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
        StringBuffer buffer = new StringBuffer();
        String line;
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }

        reader.close();
        conn.disconnect();
        log.info("RestUtils result-->" + buffer.toString());
        return buffer.toString();

    }

    private static String toCustomString(Map ht) {
        String LINE_SEPARATOR = System.getProperty("line.separator");
        StringBuffer buf = new StringBuffer();

        Object key;
        Object v;
        for (Iterator it = ht.keySet().iterator(); it.hasNext(); ) {
            key = it.next();
            v = ht.get(key);
            if (v == null) {
                buf.append(key + ":=" + null + LINE_SEPARATOR);
                break;
            }
            if (v instanceof Collection)
                v = toString(((Collection) v).toArray());
            else if (v.getClass().isArray()) {
                v = toString((Object[]) v);
            }
            buf.append(key + ":=" + v + LINE_SEPARATOR);
        }
        return buf.toString();
    }

    public static String toString(Object[] s) {
        try {
            if (s == null || s.length == 0) return "null";
            if (s.length == 1) return s[0] + "";
            String ret = "";
            for (int i = 0; i < s.length - 1; i++) {
                if (s[i].getClass().isArray()) {
                    ret += toString((Object[]) s[i]) + ",";
                }
                ret += s[i] + ",";
            }
            ret += s[s.length - 1];
            return ret;
        } catch (Exception e) {
            e.printStackTrace();
            return "internal error";
        }
    }
}
